#ifndef Define_LcBagging
#define Define_LcBagging

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include "LcBasic.h"
#include "Classifier.h"
#include "FeatureComputer.h"
#include "VideoRead.h"

using namespace std;
using namespace cv;


class LcBagging : public LcClassifier
{
public:
	int veb;

	LcBagging();

	void train( LcVideoRead & reader );

	virtual LcValidator predict(Mat & feature, Mat & res, Mat & label);
	LcValidator predict( LcVideoRead & test_reader );

	void predict( LcVideoRead & test_reader , vector< LcValidator > & validator_array);
	void predict(Mat & feature, Mat & res, Mat & label, vector< LcValidator > & validator_array);
	//these two interface is to incrementally test the preformance

	virtual void save( string filename_prefix );
	virtual void load( string filename_prefix );

	void setClassifier( LcClassifier* n_classifier);
	void setReader( LcVideoRead * n_reader );
	
	virtual void setFeatureCode( const char * n_code_string );

	int n_classifier;

	int instance_limit;

	float downsample_rate;
	int feature_dim;

	virtual LcBagging* clone() const{ return new LcBagging(*this);}

	LcClassifier * classifier_prototype;

	LcFeatureExtractor * my_extractor;
	void setExtractor( LcFeatureExtractor * n_extractor );

	vector<int> selected_id;

private:

	void initTrain();
	void initClassifier();

	void computeRate(); //compute the down sample rate.

	void append( Mat & feat    , Mat & lab,
				 Mat & feat_frm, Mat & lab_frm,
				 int & flag );

	vector< LcClassifier* > h;

	
	

	LcVideoRead * my_reader;
	const char * feature_code_string;
};

#include "ClassifierRank.h"

class LocalSensitiveBagging: public LcBagging
{
public:
	LocalSensitiveBagging();

	void set( ClassifierRank & crank, int n_classifier_n = 10, int n_instance_limit = 500000);

	void setFeatureCode( const char * n_code_string );

	void train();

	void save( string filename_prefix );
	void load( string filename_prefix );

	int knn;
	vector<int> cluster_lab;
	int cluster_n;
	Mat retrival_feature;
	LcGlobalExtractor * global_extractor;
	vector< LcVideoReadVec* > cluster_readers;

	void setReader( LcVideoRead * n_reader );

	LcValidator predict(Mat & feature, Mat & res, Mat & label, Mat & hist);

	LcValidator predict(Mat & feature, Mat & res, Mat & label, Mat & hist,
		vector< LcValidator > & validator_array);

	LcValidator predict( LcVideoRead & testreader, LcGlobalExtractor & global_extractor);

	LcValidator predict( LcVideoRead & testreader, LcGlobalExtractor & global_extractor,
		vector< LcValidator > & validator_array);

	//void setExtractor( LcFeatureExtractor * n_extractor );
	//LcFeatureExtractor * my_extractor;

	vector< LcBagging* > h;

	LcVideoRead * my_reader;

	const char * feature_code_string;
};

void testJumpReadandTrain();

#endif

